/*
 *  Copyright 2020-2025 the original author or authors.
 *  You cannot use this file unless authorized by the author.
 */

package org.ipig.commons.helper;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.ipig.constants.DateTimeCnst;
import org.ipig.model.FieldMapperConf;

import java.util.Iterator;
import java.util.Map;

/**
 * JsonHelper
 *
 * @author <a href="mailto:comchnts@163.com">chinats</a>
 * @version $$Id$$
 * @since 1.0
 */
@Slf4j
public class JsonHelper {
    /**
     * clone
     *
     * @param jsonObj JSONObject
     * @return JSONObject
     */
    public static JSONObject clone(final JSONObject jsonObj) {
        if (jsonObj == null) {
            return null;
        }
        return (JSONObject) jsonObj.clone();
    }

    /**
     * 获取第一个非空JSON对象
     *
     * @param jsonObjArgs 有序JSONObject数组
     * @return JSONObject
     */
    public static JSONObject getFirstNotBlankObject(final JSONObject... jsonObjArgs) {
        if (jsonObjArgs == null) {
            return null;
        }
        JSONObject origJsonObj = null;
        for (int i = 0; i < jsonObjArgs.length; i++) {
            if (jsonObjArgs[i] != null) {
                origJsonObj = jsonObjArgs[i];
                break;
            }
        }
        return origJsonObj;
    }

    /**
     * 对json数据的key进行字段映射
     * <ul>规则非常特殊，谨慎使用，谨慎修改</ul>
     *
     * @param fieldMapperMap 格式<field,FieldMapperConf>
     * @param jsonObject     Map<String, String>
     * @return JSONObject
     */
    public static JSONObject fieldMapper(final JSONObject jsonObject,
                                         final Map<String, FieldMapperConf> fieldMapperMap) {
        return fieldMapper(jsonObject, fieldMapperMap, false);
    }

    /**
     * 对json数据的key进行字段映射，再转驼峰
     * <ul>规则非常特殊，谨慎使用，谨慎修改</ul>
     *
     * @param fieldMapperMap 格式<field,FieldMapperConf>
     * @param jsonObject     Map<String, String>
     * @param keyToCamel     Boolean 是否将key转驼峰结构
     * @return JSONObject
     */
    public static JSONObject fieldMapper(final JSONObject jsonObject,
                                         final Map<String, FieldMapperConf> fieldMapperMap,
                                         final Boolean keyToCamel) {
        if (jsonObject == null) {
            return null;
        }
        JSONObject newJsonObject = new JSONObject();
        Iterator<Map.Entry<String, Object>> entryIterator = jsonObject.entrySet().iterator();
        while (entryIterator.hasNext()) {
            Map.Entry<String, Object> entry = entryIterator.next();
            String key = entry.getKey(), newKey = "", newValue = "";
            Object value = entry.getValue();
            FieldMapperConf fieldMapper = fieldMapperMap.get(key);
            if (fieldMapper != null) {
                newKey = fieldMapper.getToName();
                String defaultValue = fieldMapper.getDefaultValue();
                if (value == null) {
                    if (StringUtils.isBlank(defaultValue)) {
                        newValue = StringUtils.EMPTY;
                    } else {
                        newValue = defaultValue;
                    }
                } else {
                    newValue = StringUtils.trimToEmpty(StringHelper.valueOf(value));
                }

                if (StringUtils.equals(fieldMapper.getToType(), "DateTime")) {
                    if (StringUtils.isBlank(fieldMapper.getToFormatter()) ||
                            StringUtils.equals(fieldMapper.getToFormatter(), DateTimeCnst.DATE_TIME)) {
                        //目前仅处理此规则，后续进行扩展
                        if (StringUtils.isNotBlank(newValue)) {
                            newValue = DateTimeHelper.parseDateTimeToDigit(newValue);
                        }
                    }
                } else if (StringUtils.equals(fieldMapper.getFromType(), "Date")) {
                    //后续进行扩展
                    log.warn("等待处理实现！");
                }
            } else {
                if (keyToCamel) {
                    newKey = StringHelper.underlineToCamel(key);
                } else {
                    newKey = key;
                }
                if (value == null) {
                    newValue = StringUtils.EMPTY;
                } else {
                    newValue = StringUtils.trimToEmpty(StringHelper.valueOf(value));
                }
            }

            if (StringUtils.isNotBlank(newKey)) {
                newJsonObject.put(newKey, newValue);
            } else {
                log.warn("数据或映射中有字段名为空，原始key={}，原始value={},映射json={}", key, value, fieldMapper == null ? StringUtils.EMPTY : fieldMapper.toString());
            }
        }
        return newJsonObject;
    }

    /**
     * 设置JSON对象的值[直接替换覆盖]
     *
     * @param key        String
     * @param value      String
     * @param varJsonObj JSONObject
     */
    public static void setObjectValue(final String key, final String value, JSONObject varJsonObj) {
        setObjectValue(key, value, true, varJsonObj);
    }

    /**
     * 设置JSON对象的值。
     * <li>如果isReplace=true，则直接替换覆盖，
     * <li>如果isReplace=false，则先判断旧值是否存在，不存在则设置，存在则不设置，
     *
     * @param key        String
     * @param value      String
     * @param isReplace  boolean
     * @param varJsonObj JSONObject
     */
    public static void setObjectValue(final String key, final String value, final boolean isReplace, JSONObject varJsonObj) {
        if (varJsonObj != null) {
            String oldValue = StringHelper.valueOf(varJsonObj.get(key));
            String newValue = StringUtils.trimToEmpty(value);
            if (isReplace) {
                varJsonObj.put(key, newValue);
            } else {
                if (StringUtils.isBlank(oldValue)) {
                    if (StringUtils.isNotBlank(newValue)) {//不能覆盖先前的值
                        varJsonObj.put(key, newValue);
                    }
                }
            }
        }
    }

    /**
     * 将jsonStr解析成JSONObject对象并设置到map中
     * <li>注：如果jsonStr不能解析成JSONObject对象，则以K/V方式设置到map中
     *
     * @param key     String
     * @param jsonStr String
     * @param varMap  Map<String, Object>
     */
    public static void parseAndSetObject(final String key, final String jsonStr, Map<String, Object> varMap) {
        if (JSONObject.isValidObject(jsonStr)) {
            try {
                JSONObject jsonObj = JSONObject.parseObject(jsonStr);
                if (jsonObj != null) {
                    varMap.putAll(jsonObj);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } else {
            varMap.put(key, jsonStr);
        }
    }

}
